package cn.wlinker.video.monitor.service;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.wlinker.video.monitor.domain.dto.MonitorDeviceDTO;
import cn.wlinker.video.monitor.domain.Page;
import cn.wlinker.video.monitor.domain.PageQuery;
import cn.wlinker.video.monitor.domain.dto.PlayUrlDTO;
import cn.wlinker.video.monitor.domain.vo.FirstLevelDeviceVO;
import cn.wlinker.video.monitor.domain.vo.MonitorDeviceVO;
import cn.wlinker.video.monitor.domain.vo.VideoVO;
import cn.wlinker.video.monitor.enums.VideoBrandEnum;
import cn.wlinker.video.monitor.utils.MonitorDeviceCacheUtils;
import cn.wlinker.video.monitor.utils.VideoStreamCacheUtils;
import org.apache.commons.lang3.ObjectUtils;

import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 视频品牌接口
 *
 * @author gxsjx
 * @version 1.0
 * @date 2022/7/26
 */
public interface IVideoBrandEnum {

    ConcurrentHashMap<String, IVideoBrandEnum> suppliers = new ConcurrentHashMap<>(8);

    String getMonitorType();

    static IVideoBrandEnum getOne(String monitorType) {
        VideoBrandEnum.init();
        if (suppliers.containsKey(monitorType)) {
            return suppliers.get(monitorType);
        }
        throw new RuntimeException("没有找到对应的实例");
    }

    static void register(IVideoBrandEnum videoBrandEnum) {
        suppliers.put(videoBrandEnum.getMonitorType(), videoBrandEnum);
    }

    static void register(IVideoBrandEnum[] videoBrandEnums) {
        register(Arrays.asList(videoBrandEnums));
    }

    static void register(Collection<IVideoBrandEnum> videoBrandEnums) {
        videoBrandEnums.forEach(IVideoBrandEnum::register);
    }

    /**
     * 获取回放流
     * @param dto
     * @param playUrlDTO
     * @return
     */
    default VideoVO getRelayUrl(MonitorDeviceDTO dto, PlayUrlDTO playUrlDTO){
        return getVideoStream(dto).getRelayUrl(dto,playUrlDTO);
    }

    /**
     * 获取具体的流
     *
     * @param monitorDeviceDTO
     * @return
     */
    static IVideoStreamService getVideoStream(MonitorDeviceDTO monitorDeviceDTO) {
        String monitorType = monitorDeviceDTO.getMonitorType();
        String accessPlatform = monitorDeviceDTO.getAccessPlatform();
        return getOne(monitorType).getVideoStream(accessPlatform);
    }

    /**
     * 获取具体的流
     *
     * @param accessPlatform
     * @return
     */
    default IVideoStreamService getVideoStream(String accessPlatform) {
        return IVideoAccessPlatformEnum.getOne(this, accessPlatform).getFactory();
    }

    /**
     * 构建视频流
     *
     * @param dto 视频设备DTO
     * @return
     */
    default VideoVO buildStream(MonitorDeviceDTO dto, PlayUrlDTO playUrlDTO) {
        //缓存有数据直接响应
        VideoVO videoVO = VideoStreamCacheUtils.get(playUrlDTO);
        DateTime date = DateUtil.date();
        if (ObjectUtils.isNotEmpty(videoVO) && ObjectUtils.isNotEmpty(videoVO.getExpireTime()) && date.isBefore(videoVO.getExpireTime())) {
            return videoVO;
        }
        //开始构建流
        IVideoStreamService factory = getVideoStream(dto.getAccessPlatform());
        videoVO = factory.buildVideoStream(dto, playUrlDTO);
        videoVO.setId(dto.getId());
        videoVO.setName(dto.getName());
        String playUrl = videoVO.getPlayUrl();
        if(StrUtil.isNotBlank(playUrl)){
            VideoStreamCacheUtils.put(videoVO, playUrlDTO);
        }
        return videoVO;
    }

    default Page<MonitorDeviceVO> getMonitorDeviceList(String accessPlatform, String deviceCode, String status, PageQuery pageQuery) {
        IVideoStreamService factory = getVideoStream(accessPlatform);
        Page<MonitorDeviceVO> monitorDeviceVOPage = factory.getMonitorDeviceList(deviceCode, status, pageQuery);
        if (ObjectUtil.isEmpty(monitorDeviceVOPage)) {
            return monitorDeviceVOPage;
        }
        monitorDeviceVOPage.getRecords().forEach(t -> {
            t.setMonitorType(getMonitorType());
            t.setAccessPlatform(accessPlatform);
            String monitorDeviceKey = MonitorDeviceCacheUtils.getMonitorDeviceKey(t);
            t.setId(monitorDeviceKey);
            MonitorDeviceCacheUtils.put(t);
        });
        return monitorDeviceVOPage;
    }

    /**
     * 获取一级设备树
     * @return
     */
    default List<FirstLevelDeviceVO> getNetFirstLevelDeviceList(){
        return Collections.emptyList();
    }

}
